/**
 * 
 */
package com.simtek.simplayer.controller;

import java.util.ArrayList;
import java.util.List;

import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnBufferingUpdateListener;
import android.media.MediaPlayer.OnCompletionListener;
import android.media.MediaPlayer.OnErrorListener;
import android.media.MediaPlayer.OnPreparedListener;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Handler;
import android.os.Handler.Callback;
import android.os.Message;
import android.os.Vibrator;
import android.support.v4.view.MotionEventCompat;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.view.ScaleGestureDetector.OnScaleGestureListener;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnTouchListener;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.PopupWindow;
import android.widget.PopupWindow.OnDismissListener;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.TextView;
import android.widget.VideoView;

import com.simtek.simplayer.AppConfig;
import com.simtek.simplayer.FullScreenActionActivity;
import com.simtek.simplayer.R.dimen;
import com.simtek.simplayer.R.drawable;
import com.simtek.simplayer.R.id;
import com.simtek.simplayer.R.layout;
import com.simtek.simplayer.R.string;
import com.simtek.simplayer.VideoPlayerWindow;
import com.simtek.simplayer.adapter.QualityAdapter;
import com.simtek.simplayer.controller.GestureController.OnGestureListener;
import com.simtek.simplayer.entry.VideoPlayEntry;
import com.simtek.simplayer.entry.VideoTypeConstrant;
import com.simtek.simplayer.entry.YoutubeUrlMeta;
import com.simtek.simplayer.utils.StringUtils;
import com.simtek.simplayer.utils.SystemUtils;
import com.simtek.simplayer.utils.TimeUtils;
import com.simtek.simplayer.utils.VideoUtils;
import com.simtek.simplayer.utils.YoutubeUtils;
import com.simtek.simplayer.window.StandOutWindow;
import com.simtek.simplayer.window.StandOutWindow.StandOutLayoutParams;

/**
 * @author Hitech
 * 
 */
public class PlayerController implements OnClickListener, OnPreparedListener,
		OnErrorListener, OnCompletionListener, OnBufferingUpdateListener {
	private static final short		STATE_IDLE					= 0;
	private static final short		STATE_PREPAIR_URL			= 1;
	private static final short		STATE_PREPAIRING			= 2;
	private static final short		STATE_PREPAIRED				= 3;
	private static final short		STATE_FAILE					= 4;
	private static final short		STATE_COMPLETE				= 5;
	//
	protected static final long		UPDATE_PROGRESS_DELAY		= 1000;
	protected static final long		CONTROL_HIDDEN_TIMEOUT		= 3000;
	protected static final long		FADE_ANIMATION_DURATION		= 200;
	//
	private static final int		CALLBACK_HIDE_CONTROL		= 0;
	private static final int		CALLBACK_SHOW_CONTROL		= 1;
	private static final int		CALLBACK_UPDATE_PROGRESS	= 2;
	//
	private static PlayerController	instance;

	public VideoPlayEntry			playingVideoEntry;

	//
	public View						contentView;
	public View						closeButton;
	public TextView					videoTitle;
	public VideoView				video;

	public FrameLayout				blackSpan;
	public LinearLayout				controlSpan;

	public View						loadingProgress;
	public View						downloadButton;
	public ImageView				playButton;
//	public ImageView				settingButton;
	public ImageView				playerSizeButton;
	private SeekBar					seekProgress;
	private TextView				currentProgress;
	private TextView				durationText;

	private Animation				fadeIn;
	private Animation				fadeOut;

	private long					clickTouchSlop				= 200;
	private boolean					isVisibleControl			= false;
	private boolean					isLockControl				= false;

	private short					state						= STATE_IDLE;

	private Handler					handler;

	private Callback				callback;

	private TextView				seekLable;

	private GestureController		gestureController;
	private Vibrator				vibrator;
	private ImageView				lockControl;
	private ScaleGestureDetector	scaleGestureController;

	public static PlayerController getInstance() {
		if (instance == null) {
			instance = new PlayerController();
		}
		return instance;
	}

	public static void onDestroy() {
		// instance.adView.destroy();
		instance = null;
	}

	public boolean isPlayingVideoEntry(VideoPlayEntry playEntry) {
		if (playingVideoEntry == null) {
			return false;
		}

		if (playEntry != null) {
			return StringUtils.equals(playEntry.getVideoSrc(),
					playingVideoEntry.getVideoSrc());
		}

		return false;
	}

	// private AdView adView;

	public void onCreateView(final VideoPlayerWindow context,
			LayoutInflater inflater, final ViewGroup frame) {
		callback = new Callback() {
			public boolean handleMessage(Message msg) {

				switch (msg.what) {
					case CALLBACK_UPDATE_PROGRESS:
						bindProgress();
						break;
					case CALLBACK_SHOW_CONTROL:
						if (!isVisibleControl) {
							isVisibleControl = true;
							bindWindow();
						}
						break;
					case CALLBACK_HIDE_CONTROL:
						if (video.isPlaying()) {
							if (isVisibleControl) {
								isVisibleControl = false;
								bindWindow();
							}
						} else {
							isVisibleControl = true;
							bindWindow();
						}
						break;
					default:
						return false;
				}
				return true;
			}
		};
		if (handler == null) {
			handler = new Handler(callback);
		}
		fadeIn = AnimationUtils.loadAnimation(context, android.R.anim.fade_in);
		fadeOut = AnimationUtils
				.loadAnimation(context, android.R.anim.fade_out);

		fadeIn.setDuration(FADE_ANIMATION_DURATION);
		fadeOut.setDuration(FADE_ANIMATION_DURATION);

		scaleGestureController = new ScaleGestureDetector(context,
				new OnScaleGestureListener() {
					boolean	isHandled;

					@Override
					public void onScaleEnd(ScaleGestureDetector detector) {
					}

					@Override
					public boolean onScaleBegin(ScaleGestureDetector detector) {
						isHandled = false;
						return true;
					}

					@Override
					public boolean onScale(ScaleGestureDetector detector) {
						float factor = detector.getScaleFactor();

						if (factor == 1) {
							return false;
						}

						if (!isHandled) {
							switch (VideoPlayerWindow.currentScreenMode) {
								case VideoPlayerWindow.WINDOW_MODE_MINIMIZE:
									if (factor > 1) {
										VideoPlayerWindow.showFullWidth(video
												.getContext());
									}
									break;
								case VideoPlayerWindow.WINDOW_MODE_FULLSCREEN_WIDTH:
									if (factor > 1) {
										VideoPlayerWindow.showFullScreen(video
												.getContext());
									} else {
										VideoPlayerWindow.showMinizeWindow(video
												.getContext());
									}
									break;
								case VideoPlayerWindow.WINDOW_MODE_FULLSCREEN:
									if (factor < 1) {
										VideoPlayerWindow.showFullWidth(video
												.getContext());
									}
									break;
							}
							isHandled = true;
						}
						return true;
					}
				});

		gestureController = new GestureController(context, frame.getHandler(),
				new GestureHandler(context, frame));

		gestureController.setHorizontalSeekable(false);
		gestureController.setVerticalSeekable(false);

		context.setOnWindowTouchListener(new OnTouchListener() {
			boolean	scaleInProcess;

			@SuppressLint("ClickableViewAccessibility")
			@Override
			public boolean onTouch(View arg0, MotionEvent event) {
				switch (event.getAction()) {
					case MotionEvent.ACTION_DOWN:
						scaleInProcess = false;
						if (!isVisibleControl) {
							handler.sendEmptyMessageDelayed(CALLBACK_SHOW_CONTROL,
									Math.max(100, clickTouchSlop));
							handler.removeMessages(CALLBACK_HIDE_CONTROL);
						}
						break;
				}

				//
				if (MotionEventCompat.getPointerCount(event) > 1) {
					scaleInProcess = true;
					return scaleGestureController.onTouchEvent(event);
				} else if (scaleInProcess) {
					return true;
				}

				//
				return gestureController.onTouch(arg0, event);
			}
		});

		contentView = inflater.inflate(layout.player_window_layout, frame,
				false);

		video = (VideoView) contentView.findViewById(id.player_window_video);
		video.getHolder().setSizeFromLayout();
		video.setOnPreparedListener(this);
		video.setOnErrorListener(this);
		video.setOnCompletionListener(this);

		//
		loadingProgress = contentView
				.findViewById(id.player_window_watting_progress);
		blackSpan = (FrameLayout) contentView
				.findViewById(id.player_window_linearBlackSpan);
		controlSpan = (LinearLayout) contentView
				.findViewById(id.player_window_control_span);

		seekProgress = (SeekBar) contentView
				.findViewById(id.player_window_progress_seek);
		seekProgress.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {

			@Override
			public void onStopTrackingTouch(SeekBar seekBar) {
				handler.removeMessages(CALLBACK_HIDE_CONTROL);
				handler.sendEmptyMessageDelayed(CALLBACK_HIDE_CONTROL,
						CONTROL_HIDDEN_TIMEOUT);
			}

			@Override
			public void onStartTrackingTouch(SeekBar seekBar) {
				handler.removeMessages(CALLBACK_HIDE_CONTROL);
			}

			@Override
			public void onProgressChanged(SeekBar seekBar, int progress,
					boolean fromUser) {
				if (fromUser) {
					if (state >= STATE_PREPAIRED) {
						video.seekTo(progress);
						bindProgress();
					}
				}
			}
		});

		// adView = (AdView) contentView.findViewById(id.adview);

		videoTitle = (TextView) contentView
				.findViewById(id.player_window_video_title);
		downloadButton = contentView
				.findViewById(id.player_window_download_button);
		closeButton = contentView.findViewById(id.player_window_close_button);
		playButton = (ImageView) contentView
				.findViewById(id.player_window_play_button);
//		settingButton = (ImageView) contentView
//				.findViewById(id.player_window_menu_button);
		playerSizeButton = (ImageView) contentView
				.findViewById(id.player_window_size_button);
		currentProgress = (TextView) contentView
				.findViewById(id.player_window_progress_time);
		durationText = (TextView) contentView
				.findViewById(id.player_window_progress_duration);
		seekLable = (TextView) contentView
				.findViewById(id.player_window_seek_lable);
		lockControl = (ImageView) contentView
				.findViewById(id.player_window_lock_control_button);

		//
		downloadButton.setOnClickListener(this);
		closeButton.setOnClickListener(this);
		playButton.setOnClickListener(this);
//		settingButton.setOnClickListener(this);
		playerSizeButton.setOnClickListener(this);
		lockControl.setOnClickListener(this);
	}

	private int	lastSeek	= -1;

	@TargetApi(Build.VERSION_CODES.HONEYCOMB)
	private void doVibrator(float percent) {
		if (lastSeek == -1
				|| (lastSeek != (int) percent && (int) percent % 5 == 0)) {
			vibrator.vibrate(20);
		}
		lastSeek = (int) percent;
	}

	@Override
	public void onClick(View v) {
		try {
			switch (v.getId()) {
				case id.player_window_download_button:
					showDownloadSelection(v);
					break;
				case id.player_window_close_button:
					video.stopPlayback();
					StandOutWindow
							.closeAll(v.getContext(), VideoPlayerWindow.class);
					FullScreenActionActivity.hide(v.getContext());

					break;
				case id.player_window_play_button:
					togglePlayVideo();
					break;
				case id.player_window_lock_control_button:
					isLockControl = false;
					bindWindow();
					break;
//				case id.player_window_menu_button:
//					showOptionMenu(v);
				case id.player_window_size_button:
					toggleScreenMode();
					break;
			}

			handler.removeMessages(CALLBACK_HIDE_CONTROL);
			handler.sendEmptyMessageDelayed(CALLBACK_HIDE_CONTROL,
					CONTROL_HIDDEN_TIMEOUT);
		} catch (Throwable e) {
			e.printStackTrace();
		}
	}

	private void togglePlayVideo() {
		if (state >= STATE_PREPAIRED) {
			if (video.isPlaying()) {
				video.pause();
				video.setKeepScreenOn(false);
				isVisibleControl = true;
			} else {
				video.setKeepScreenOn(true);
				video.start();
			}
			state = STATE_PREPAIRED;
			bindWindow();
		}
	}

	public void onCreate(Context context) {
		vibrator = (Vibrator) context
				.getSystemService(Context.VIBRATOR_SERVICE);
		final ViewConfiguration configuration = ViewConfiguration.get(context);
		clickTouchSlop = configuration.getScaledTouchSlop();

		AppConfig.createInstance(context);

		if (handler == null) {
			handler = new Handler(callback);
		}

		state = STATE_IDLE;
		isVisibleControl = true;

		loadVideo();
	}

	// private void showAdView() {
	// AdRequest.Builder request = new AdRequest.Builder();
	// if (adView.getAdListener() == null) {
	// adView.loadAd(request.build());
	// adView.setAdListener(new AdListener() {
	// @Override
	// public void onAdLoaded() {
	// // TODO Auto-generated method stub
	// super.onAdLoaded();
	// }
	//
	// @Override
	// public void onAdFailedToLoad(int errorCode) {
	// // TODO Auto-generated method stub
	// super.onAdFailedToLoad(errorCode);
	// }
	// });
	// } else {
	// adView.resume();
	// }
	// adView.setVisibility(View.VISIBLE);
	// }
	//
	// private void hideAdView() {
	// adView.pause();
	// adView.setVisibility(View.INVISIBLE);
	// }

	private void loadVideo() {
		seekProgress.setSecondaryProgress(0);

		if (playingVideoEntry != null) {
			switch (playingVideoEntry.getSrcType()) {
				case VideoTypeConstrant.TYPE_VIDEO_HTTP:
				case VideoTypeConstrant.TYPE_VIDEO_LOCAL:
					video.stopPlayback();
					if (playingVideoEntry.isPlaylist()) {
						if (playingVideoEntry.getCurrentEntry().getUri() != null) {
							video.setVideoURI(playingVideoEntry.getUri());
						} else {
							video.setVideoPath(playingVideoEntry.getCurrentEntry()
									.getVideoSrc());
						}
					} else {
						if (playingVideoEntry.getUri() != null) {
							video.setVideoURI(playingVideoEntry.getUri());
						} else {
							video.setVideoPath(playingVideoEntry.getVideoSrc());
						}
					}
					state = STATE_PREPAIRING;
					break;

				case VideoTypeConstrant.TYPE_VIDEO_YOUTUBE:
					if (playingVideoEntry.isFailed()) {
						state = STATE_FAILE;
					} else {
						if (playingVideoEntry.getContentUrl() == null) {
							fetchYoutubeInfo();
							state = STATE_PREPAIR_URL;
						} else {
							YoutubeUrlMeta currentYoutubeUrl = playingVideoEntry.getCurrentYoutubeUrl();
							if (currentYoutubeUrl != null) {
								video.setVideoPath(currentYoutubeUrl.getVideoSrc());
							} else {
								int[] size = SystemUtils.getDisplaySize(video.getContext());
								if (size != null) {
									currentYoutubeUrl = VideoUtils.getBestVideoSize(video.getContext(), playingVideoEntry.getContentUrl());
									if (currentYoutubeUrl != null) {
										Log.d("video", "***playing size #" + currentYoutubeUrl.width + "x" + currentYoutubeUrl.height);
										playingVideoEntry.setCurrentUrl(currentYoutubeUrl);
										video.setVideoPath(currentYoutubeUrl.getVideoSrc());
									} else {
										// TODO
									}
								}
							}
							state = STATE_PREPAIRING;
						}
					}
					
					break;
			}
		}
		bindWindow();
	}

	private void fetchYoutubeInfo() {
		new AsyncTask<VideoPlayEntry, Void, VideoPlayEntry>() {
			@Override
			protected VideoPlayEntry doInBackground(VideoPlayEntry... params) {
				VideoPlayEntry entry = params[0];
				YoutubeUtils.loadYoutubeInfo(entry);
				return entry;
			}

			@Override
			protected void onPostExecute(VideoPlayEntry result) {
				loadVideo();
				VideoPlayerWindow.updateWindow(video.getContext());
			}
		}.execute(playingVideoEntry);
	}

	public void bindWindow() {
		if (isLockControl) {
			setVisibleView(lockControl, View.VISIBLE);
			seekProgress.setEnabled(false);
		} else {
			setVisibleView(lockControl, View.GONE);
			seekProgress.setEnabled(true);
		}

		//
		if (isVisibleControl) {
			// auto hide control delay
			handler.removeMessages(CALLBACK_HIDE_CONTROL);
			handler.sendEmptyMessageDelayed(CALLBACK_HIDE_CONTROL,
					CONTROL_HIDDEN_TIMEOUT);

			// set control visibility
			setVisibleView(videoTitle, View.VISIBLE);
			setVisibleView(playButton, View.VISIBLE);
			setVisibleView(controlSpan, View.VISIBLE);
			setVisibleView(seekProgress, View.VISIBLE);
			setVisibleView(closeButton, View.VISIBLE);

//			setVisibleView(settingButton, isLockControl ? View.GONE
//					: View.VISIBLE);
			setVisibleView(playerSizeButton, isLockControl ? View.GONE : View.VISIBLE);

			// download button visibility base on video type
			switch (playingVideoEntry.getSrcType()) {
				case VideoTypeConstrant.TYPE_VIDEO_HTTP:
				case VideoTypeConstrant.TYPE_VIDEO_YOUTUBE:
					setVisibleView(downloadButton,
							state == STATE_PREPAIR_URL ? View.GONE : View.VISIBLE);
					break;
				default:
					setVisibleView(downloadButton, View.GONE);
					break;
			}

			switch (VideoPlayerWindow.currentScreenMode) {
				case VideoPlayerWindow.WINDOW_MODE_MINIMIZE:
					gestureController.setHorizontalSeekable(false);
					gestureController.setVerticalSeekable(false);
					//
					setVisibleView(currentProgress, View.GONE);
					setVisibleView(durationText, View.GONE);
					break;
				case VideoPlayerWindow.WINDOW_MODE_FULLSCREEN_WIDTH:
					gestureController.setHorizontalSeekable(true);
					gestureController.setVerticalSeekable(false);
					//
					bindProgress();
					setVisibleView(currentProgress, View.VISIBLE);
					setVisibleView(durationText, View.VISIBLE);
					break;
				case VideoPlayerWindow.WINDOW_MODE_FULLSCREEN:
					gestureController.setHorizontalSeekable(true);
					gestureController.setVerticalSeekable(true);
					//
					bindProgress();
					setVisibleView(currentProgress, View.VISIBLE);
					setVisibleView(durationText, View.VISIBLE);
					break;
			}

			videoTitle.setText(playingVideoEntry.getCurrentTitle());
			video.setKeepScreenOn(video.isPlaying());
			playButton
					.setImageResource(video.isPlaying() ? drawable.ic_vidcontrol_pause
							: drawable.ic_vidcontrol_play);
//			settingButton
//					.setSelected(VideoPlayerWindow.currentScreenMode == VideoPlayerWindow.WINDOW_MODE_FULLSCREEN
//							|| VideoPlayerWindow.currentScreenMode == VideoPlayerWindow.WINDOW_MODE_FULLSCREEN_WIDTH);
		} else {
//			setVisibleView(settingButton, View.GONE);
			setVisibleView(playerSizeButton, View.GONE);
			setVisibleView(playButton, View.GONE);
			setVisibleView(videoTitle, View.GONE);
			setVisibleView(closeButton, View.GONE);
			setVisibleView(downloadButton, View.GONE);
			setVisibleView(durationText, View.INVISIBLE);
			setVisibleView(currentProgress, View.INVISIBLE);
			setVisibleView(controlSpan, View.INVISIBLE);
			setVisibleView(seekProgress, View.INVISIBLE);

//			Object tag = settingButton.getTag();
//			if (tag != null && tag instanceof PopupWindow) {
//				((PopupWindow) tag).dismiss();
//			}
		}

		//

		// bind window state
		switch (state) {
			case STATE_IDLE:
				playButton.setEnabled(false);
				blackSpan.setBackgroundColor(Color.BLACK);
				setVisibleView(loadingProgress, View.VISIBLE);
				break;
			case STATE_PREPAIR_URL:
				playButton.setEnabled(false);
				blackSpan.setBackgroundColor(Color.BLACK);
				setVisibleView(loadingProgress, View.VISIBLE);
				break;
			case STATE_PREPAIRING:
				playButton.setEnabled(false);
				blackSpan.setBackgroundColor(Color.BLACK);
				setVisibleView(loadingProgress, View.VISIBLE);
				break;
			case STATE_FAILE:
				playButton.setEnabled(isLockControl ? false : true);
				playButton.setImageResource(drawable.btn_player_replay);
				blackSpan.setBackgroundColor(Color.BLACK);
				setVisibleView(loadingProgress, View.GONE);
				break;
			case STATE_PREPAIRED:
				playButton.setEnabled(isLockControl ? false : true);
				blackSpan.setBackgroundColor(Color.TRANSPARENT);
				setVisibleView(loadingProgress, View.GONE);
				break;
			case STATE_COMPLETE:
				playButton.setEnabled(isLockControl ? false : true);
				blackSpan.setBackgroundColor(Color.BLACK);
				setVisibleView(loadingProgress, View.GONE);
				break;
		}
	}

	private void toggleScreenMode() {
		switch (VideoPlayerWindow.currentScreenMode) {
			case VideoPlayerWindow.WINDOW_MODE_MINIMIZE:
				VideoPlayerWindow.showFullWidth(video.getContext());
				break;
			case VideoPlayerWindow.WINDOW_MODE_FULLSCREEN_WIDTH:
				VideoPlayerWindow.showFullScreen(video.getContext());
				break;
			case VideoPlayerWindow.WINDOW_MODE_FULLSCREEN:
				VideoPlayerWindow.showMinizeWindow(video.getContext());
				break;
		}
	}

	private void setVisibleView(View v, int visibility) {
		v.clearAnimation();

		if (v.getVisibility() == visibility) {
			return;
		}

		if (v.getVisibility() != visibility) {
			switch (visibility) {
				case View.VISIBLE:
					v.startAnimation(fadeIn);
					break;
				default:
					v.startAnimation(fadeOut);
					break;
			}
			v.setVisibility(visibility);
		}
	}

	public void bindProgress() {
		handler.removeMessages(CALLBACK_UPDATE_PROGRESS);
		if (video.isPlaying()) {
			handler.sendEmptyMessageDelayed(CALLBACK_UPDATE_PROGRESS,
					UPDATE_PROGRESS_DELAY);
		}

		switch (state) {
			case STATE_IDLE:
				seekProgress.setProgress(0);
				break;
			case STATE_PREPAIR_URL:
				break;
			case STATE_PREPAIRING:
				break;
			case STATE_PREPAIRED:
				seekProgress.setMax(video.getDuration());
				seekProgress.setProgress(video.getCurrentPosition());

				//
				currentProgress.setText(TimeUtils.getDuration(
						video.getCurrentPosition(), ":"));
				durationText
						.setText(TimeUtils.getDuration(video.getDuration(), ":"));
				break;
			case STATE_FAILE:
				seekProgress.setProgress(0);
				break;
			case STATE_COMPLETE:
				seekProgress.setProgress(0);
				break;
		}
	}

	public void setVideoSrc(VideoPlayEntry v) {
		playingVideoEntry = v;
	}

	@Override
	public void onPrepared(MediaPlayer player) {
		state = STATE_PREPAIRED;
		bindWindow();

		player.setScreenOnWhilePlaying(true);
		player.setOnBufferingUpdateListener(this);

		player.start();
		player.seekTo(playingVideoEntry.getPlayProgress());

	}

	public void onBufferingUpdate(MediaPlayer mp, int percent) {
		seekProgress.setSecondaryProgress(percent * mp.getDuration()
				/ 100);
	}

	@Override
	public boolean onError(MediaPlayer arg0, int arg1, int arg2) {
		state = STATE_FAILE;
		bindWindow();
		return true;
	}

	@Override
	public void onCompletion(MediaPlayer player) {
		isVisibleControl = true;
		state = STATE_COMPLETE;
		video.setKeepScreenOn(false);
		bindProgress();
		bindWindow();

		if (FullScreenActionActivity.getInstance() != null) {
			FullScreenActionActivity.getInstance().getWindow()
					.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
		}
	}

	private void showOptionMenu(final View v) {
		final Resources resources = v.getResources();

		final List<String> data = new ArrayList<String>();
		switch (playingVideoEntry.getSrcType()) {
			case VideoTypeConstrant.TYPE_VIDEO_LOCAL:

				break;
			case VideoTypeConstrant.TYPE_VIDEO_HTTP:

				break;
			case VideoTypeConstrant.TYPE_VIDEO_YOUTUBE:
				if (state > STATE_PREPAIR_URL) {
					String qualityLable = resources
							.getString(string.string_quality);
					YoutubeUrlMeta currentYoutubeUrl = playingVideoEntry
							.getCurrentYoutubeUrl();
					if (currentYoutubeUrl != null) {
						qualityLable += " (" + currentYoutubeUrl.height + "p)";
					}
					data.add(qualityLable);
				}
				break;
			default:
				return;
		}
		if (isLockControl) {
			data.add(resources.getString(string.string_unlock_control));
		} else {
			data.add(resources.getString(string.string_lock_control));
		}
		data.add(resources.getString(string.string_setting));

		if (data.isEmpty()) {
			return;
		}

		ArrayAdapter<String> menuAdapter = new ArrayAdapter<String>(
				v.getContext(), layout.qualitiy_item_layout,
				id.txtOptionMenuItem, data);

		handler.removeMessages(CALLBACK_HIDE_CONTROL);
		ListView listView = new ListView(v.getContext());
		listView.setAdapter(menuAdapter);
		final PopupWindow dropDown = new PopupWindow(listView,
				resources.getDimensionPixelSize(dimen.window_menu_width),
				StandOutLayoutParams.WRAP_CONTENT, true);
		dropDown.setBackgroundDrawable(resources
				.getDrawable(android.R.drawable.editbox_dropdown_dark_frame));
		listView.setOnItemClickListener(new OnItemClickListener() {
			public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
					long arg3) {
				String action = data.get(arg2);
				if (action.equals(resources
						.getString(string.string_lock_control))) {
					isLockControl = true;
					isVisibleControl = false;
					bindWindow();
				} else if (action.equals(resources
						.getString(string.string_unlock_control))) {
					isLockControl = false;
					isVisibleControl = false;
					bindWindow();
				} else if (action.startsWith(resources
						.getString(string.string_quality))) {
					showQualitySelection(v);
				} else if (action.equals(resources
						.getString(string.string_setting))) {
					showSettingPopup(arg1.getContext(), dropDown);
				}
				dropDown.dismiss();
			}
		});

		dropDown.setOnDismissListener(new OnDismissListener() {
			public void onDismiss() {
				v.setTag(null);
			}
		});

		v.setTag(dropDown);
		dropDown.showAsDropDown(v);
	}

	private void showSettingPopup(Context context, PopupWindow parentDropdown) {
	}

	@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
	private void showDownloadSelection(final View v) {
		if (playingVideoEntry.getSrcType() == VideoTypeConstrant.TYPE_VIDEO_HTTP) {
			VideoDownloadController.downloadVideoUrl(v.getContext(), playingVideoEntry.getUri().toString(), playingVideoEntry.getTitle(), "mp4");
		} else if (playingVideoEntry.getSrcType() == VideoTypeConstrant.TYPE_VIDEO_YOUTUBE) {
			handler.removeMessages(CALLBACK_HIDE_CONTROL);
			ListView listView = new ListView(v.getContext());
			QualityAdapter qualityAdapter = new QualityAdapter(v.getContext());

			if (playingVideoEntry != null
					&& playingVideoEntry.getCurrentYoutubeUrl() != null) {
				qualityAdapter.setData(playingVideoEntry.getContentUrl());
			} else {
				return;
			}

			listView.setAdapter(qualityAdapter);

			final PopupWindow dropDown = new PopupWindow(listView, v
					.getResources().getDimensionPixelSize(
							dimen.window_menu_width),
					StandOutLayoutParams.WRAP_CONTENT, true);
			Drawable background = v.getResources().getDrawable(
					android.R.drawable.editbox_dropdown_dark_frame);
			dropDown.setBackgroundDrawable(background);
			listView.setOnItemClickListener(new OnItemClickListener() {
				public void onItemClick(AdapterView<?> arg0, View arg1,
						int arg2, long arg3) {
					try {
						YoutubeUrlMeta item = (YoutubeUrlMeta) arg0
								.getAdapter().getItem(arg2);
						VideoDownloadController.downloadVideoUrl(
								v.getContext(), item.getVideoSrc(),
								item.getTitle(), item.getExtention());
					} catch (Throwable e) {
						e.printStackTrace();
					}
					handler.sendEmptyMessageDelayed(CALLBACK_HIDE_CONTROL,
							CONTROL_HIDDEN_TIMEOUT);
					dropDown.dismiss();
				}
			});
			dropDown.showAsDropDown(v);
		}
	}

	@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
	private void showQualitySelection(View v) {
		handler.removeMessages(CALLBACK_HIDE_CONTROL);
		ListView listView = new ListView(v.getContext());

		QualityAdapter qualityAdapter = new QualityAdapter(v.getContext());

		if (playingVideoEntry != null
				&& playingVideoEntry.getCurrentYoutubeUrl() != null) {
			qualityAdapter.setData(playingVideoEntry.getContentUrl());
		} else {
			return;
		}
		listView.setAdapter(qualityAdapter);

		final PopupWindow dropDown = new PopupWindow(listView, v.getResources()
				.getDimensionPixelSize(dimen.window_menu_width),
				StandOutLayoutParams.WRAP_CONTENT, true);
		Drawable background = v.getResources().getDrawable(
				android.R.drawable.editbox_dropdown_dark_frame);
		dropDown.setBackgroundDrawable(background);
		listView.setOnItemClickListener(new OnItemClickListener() {
			public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
					long arg3) {
				try {
					YoutubeUrlMeta item = (YoutubeUrlMeta) arg0.getAdapter()
							.getItem(arg2);
					playingVideoEntry.setCurrentUrl(item);
					playingVideoEntry.setPlayProgress(video
							.getCurrentPosition());
					loadVideo();
				} catch (Throwable e) {
					e.printStackTrace();
				}
				handler.sendEmptyMessageDelayed(CALLBACK_HIDE_CONTROL,
						CONTROL_HIDDEN_TIMEOUT);
				dropDown.dismiss();
			}
		});
		dropDown.showAsDropDown(v);
	}

	public void onWindowModeChange(short screenMode) {
		video.getHolder().setSizeFromLayout();
		bindWindow();
	}

	public void onWindowRatioChange() {
		bindWindow();
		video.requestLayout();
	}

	private final class GestureHandler implements OnGestureListener {
		private final VideoPlayerWindow	context;
		private final ViewGroup			frame;
		private float					volumePecent;

		private GestureHandler(VideoPlayerWindow context, ViewGroup frame) {
			this.context = context;
			this.frame = frame;
		}

		@Override
		public boolean onStartSeek(int seekMode) {
			if (isLockControl) {
				return false;
			}
			seekLable.setText("");
			seekLable.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);
			volumePecent = SystemUtils.getVolumePercent(context,
					AudioManager.STREAM_MUSIC);

			if (isVisibleControl) {
				isVisibleControl = false;
				handler.removeMessages(CALLBACK_HIDE_CONTROL);
				bindWindow();
			}

			setVisibleView(seekLable, View.VISIBLE);
			setVisibleView(seekProgress, View.VISIBLE);
			bindProgress();

			lastSeek = -1;
			return true;
		}

		@Override
		public void onStopSeek(int seekMode) {
			if (isLockControl) {
				return;
			}
			setVisibleView(seekLable, View.INVISIBLE);
			setVisibleView(seekProgress, View.INVISIBLE);
		}

		@Override
		public boolean onSeek(int seekMode, float distance) {
			if (isLockControl) {
				return false;
			}

			//
			switch (VideoPlayerWindow.currentScreenMode) {
				case VideoPlayerWindow.WINDOW_MODE_MINIMIZE:
					return false;
				case VideoPlayerWindow.WINDOW_MODE_FULLSCREEN_WIDTH:
					if (seekMode != GestureController.SEEK_HORIZONTAL) {
						return false;
					}
			}

			//
			switch (seekMode) {
				case GestureController.SEEK_HORIZONTAL:
					if (Math.abs(distance) != 0) {
						int newPosition = (int) (video.getCurrentPosition() + distance * 100);
						newPosition = Math.min(Math.max(newPosition, 0),
								video.getDuration());
						video.seekTo(newPosition);
						seekLable.setText(TimeUtils.getDuration(newPosition, ":"));
						seekLable.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0,
								0);
						bindProgress();
					}
					break;
				case GestureController.SEEK_LEFT_VERTICAL:
					FullScreenActionActivity fullScreenActivity = FullScreenActionActivity
							.getInstance();
					if (fullScreenActivity != null) {
						float value = SystemUtils.seekActivityScreenBrightness(
								fullScreenActivity,
								distance * 1.5f / frame.getMeasuredHeight());

						seekLable.setText((int) (value * 100) + "%");
						seekLable.setCompoundDrawablesWithIntrinsicBounds(0,
								drawable.ic_action_brightness_high, 0, 0);
						doVibrator(value * 100);
					}
					break;
				case GestureController.SEEK_RIGHT_VERTICAL:
					float seekPercent = distance * 150 / frame.getMeasuredHeight();
					volumePecent += seekPercent;
					volumePecent = Math.min(Math.max(volumePecent, 0), 100);

					SystemUtils.setVolumePercent(context,
							AudioManager.STREAM_MUSIC, volumePecent);

					seekLable.setText((int) volumePecent + "%");
					seekLable.setCompoundDrawablesWithIntrinsicBounds(0,
							drawable.ic_action_volume_on, 0, 0);
					doVibrator(volumePecent);
					break;
			}
			return true;
		}

		@Override
		public boolean onDoubleTab() {
			toggleScreenMode();
			return true;
		}

		@Override
		public boolean onSingleTab() {
			// if (isLockControl) {
			// return false;
			// }
			// if (isVisibleControl) {
			// if (state == STATE_PREPAIRED) {
			// if (mVideoView.isPlaying()) {
			// mVideoView.pause();
			// mVideoView.setKeepScreenOn(false);
			// isVisibleControl = true;
			// } else {
			// mVideoView.setKeepScreenOn(true);
			// mVideoView.start();
			// }
			// bindWindow();
			// }
			// }
			// return true;
			return false;
		}
	}
}
